"""
环境配置管理模块
支持多环境配置（开发、测试、生产等），类似Java Spring Profile
"""
from typing import Optional, Literal
from functools import lru_cache
import os
from pathlib import Path

from pydantic_settings import BaseSettings
from pydantic import Field, validator


# 环境类型定义
Environment = Literal["development", "testing", "staging", "production"]


class BaseConfig(BaseSettings):
    """基础配置类"""
    
    # 环境配置
    environment: Environment = Field(default="development", description="运行环境")
    app_name: str = Field(default="设备管理系统", description="应用名称")
    app_version: str = Field(default="1.0.0", description="应用版本")
    debug: bool = Field(default=True, description="调试模式")
    
    # 服务器配置
    host: str = Field(default="0.0.0.0", description="服务器地址")
    port: int = Field(default=8088, description="服务器端口")
    
    # JWT配置
    secret_key: str = Field(default="your-secret-key-change-this-in-production", description="JWT密钥")
    algorithm: str = Field(default="HS256", description="JWT算法")
    access_token_expire_minutes: int = Field(default=30, description="访问令牌过期时间(分钟)")
    refresh_token_expire_days: int = Field(default=7, description="刷新令牌过期时间(天)")
    
    # 数据库配置
    database_url: str = Field(default="postgresql://deviceuser:devicepass@localhost:5432/devicedb", description="数据库连接URL")
    database_echo: bool = Field(default=False, description="数据库SQL日志")
    database_pool_size: int = Field(default=10, description="数据库连接池大小")
    database_max_overflow: int = Field(default=20, description="数据库连接池最大溢出")
    
    # Redis配置
    redis_url: str = Field(default="redis://localhost:6379/0", description="Redis连接URL")
    redis_password: Optional[str] = Field(default=None, description="Redis密码")
    redis_db: int = Field(default=0, description="Redis数据库索引")
    redis_max_connections: int = Field(default=50, description="Redis最大连接数")
    
    # 日志配置
    log_level: str = Field(default="INFO", description="日志级别")
    log_file: Optional[str] = Field(default=None, description="日志文件路径")
    log_max_size: str = Field(default="100MB", description="日志文件最大大小")
    log_backup_count: int = Field(default=5, description="日志文件备份数量")
    log_format: str = Field(default="%(asctime)s - %(name)s - %(levelname)s - %(message)s", description="日志格式")
    
    # 安全配置
    cors_origins: list[str] = Field(default=["http://localhost:3000", "http://127.0.0.1:3000"], description="CORS允许的源")
    cors_allow_credentials: bool = Field(default=True, description="CORS允许凭证")
    cors_allow_methods: list[str] = Field(default=["*"], description="CORS允许的方法")
    cors_allow_headers: list[str] = Field(default=["*"], description="CORS允许的请求头")
    
    # API配置
    api_v1_prefix: str = Field(default="/api/v1", description="API v1前缀")
    docs_url: Optional[str] = Field(default="/docs", description="API文档URL")
    redoc_url: Optional[str] = Field(default="/redoc", description="ReDoc文档URL")
    openapi_url: Optional[str] = Field(default="/openapi.json", description="OpenAPI JSON URL")
    
    # 邮件配置
    smtp_server: Optional[str] = Field(default=None, description="SMTP服务器")
    smtp_port: int = Field(default=587, description="SMTP端口")
    smtp_username: Optional[str] = Field(default=None, description="SMTP用户名")
    smtp_password: Optional[str] = Field(default=None, description="SMTP密码")
    smtp_tls: bool = Field(default=True, description="SMTP使用TLS")
    mail_from: Optional[str] = Field(default=None, description="发件人邮箱")
    
    # 文件上传配置
    upload_dir: str = Field(default="uploads", description="文件上传目录")
    max_file_size: int = Field(default=10 * 1024 * 1024, description="最大文件大小(字节)")
    allowed_file_types: list[str] = Field(default=[".jpg", ".jpeg", ".png", ".gif", ".pdf", ".doc", ".docx"], description="允许的文件类型")
    
    # 定时任务配置
    scheduler_enabled: bool = Field(default=True, description="启用定时任务调度器")
    scheduler_timezone: str = Field(default="Asia/Shanghai", description="调度器时区")
    scheduler_max_workers: int = Field(default=20, description="调度器最大工作线程数")
    
    # 监控配置
    metrics_enabled: bool = Field(default=False, description="启用监控指标")
    metrics_path: str = Field(default="/metrics", description="监控指标路径")
    health_check_path: str = Field(default="/health", description="健康检查路径")
    
    @validator('environment')
    def validate_environment(cls, v):
        allowed_envs = ['development', 'testing', 'staging', 'production']
        if v not in allowed_envs:
            raise ValueError(f'Environment must be one of {allowed_envs}')
        return v
    
    @validator('log_level')
    def validate_log_level(cls, v):
        allowed_levels = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
        if v.upper() not in allowed_levels:
            raise ValueError(f'Log level must be one of {allowed_levels}')
        return v.upper()
    
    class Config:
        case_sensitive = False
        validate_assignment = True


class DevelopmentConfig(BaseConfig):
    """开发环境配置"""
    environment: Environment = "development"
    debug: bool = True
    log_level: str = "DEBUG"
    database_echo: bool = True
    docs_url: Optional[str] = "/docs"
    redoc_url: Optional[str] = "/redoc"
    
    # 开发环境数据库（使用本地PostgreSQL）
    database_url: str = "postgresql://deviceuser:devicepass@localhost:5432/devicedb_dev"
    redis_url: str = "redis://localhost:6379/0"
    
    class Config:
        env_file = ".env.development"
        env_file_encoding = 'utf-8'


class TestingConfig(BaseConfig):
    """测试环境配置"""
    environment: Environment = "testing"
    debug: bool = True
    log_level: str = "DEBUG"
    
    # 测试环境数据库（使用内存SQLite）
    database_url: str = "sqlite:///./test_devicedb.db"
    redis_url: str = "redis://localhost:6379/1"
    
    # 测试环境特殊配置
    access_token_expire_minutes: int = 5  # 较短的token过期时间便于测试
    scheduler_enabled: bool = False  # 测试时禁用定时任务
    
    class Config:
        env_file = ".env.testing"
        env_file_encoding = 'utf-8'


class StagingConfig(BaseConfig):
    """预发布环境配置"""
    environment: Environment = "staging"
    debug: bool = False
    log_level: str = "INFO"
    database_echo: bool = False
    
    # 预发布环境数据库
    database_url: str = "postgresql://deviceuser:devicepass@staging-db:5432/devicedb_staging"
    redis_url: str = "redis://staging-redis:6379/0"
    
    # 生产级别的安全配置
    secret_key: str = "staging-secret-key-must-be-changed"
    cors_origins: list[str] = ["https://staging.device-management.com"]
    
    # 禁用文档
    docs_url: Optional[str] = None
    redoc_url: Optional[str] = None
    openapi_url: Optional[str] = None
    
    class Config:
        env_file = ".env.staging"
        env_file_encoding = 'utf-8'


class ProductionConfig(BaseConfig):
    """生产环境配置"""
    environment: Environment = "production"
    debug: bool = False
    log_level: str = "WARNING"
    database_echo: bool = False
    
    # 生产环境数据库
    database_url: str = "postgresql://deviceuser:devicepass@prod-db:5432/devicedb"
    redis_url: str = "redis://prod-redis:6379/0"
    
    # 生产环境安全配置
    secret_key: str = "production-secret-key-must-be-set-via-env"
    cors_origins: list[str] = ["https://device-management.com"]
    
    # 生产环境性能配置
    database_pool_size: int = 20
    database_max_overflow: int = 40
    redis_max_connections: int = 100
    
    # 禁用文档和调试功能
    docs_url: Optional[str] = None
    redoc_url: Optional[str] = None
    openapi_url: Optional[str] = None
    
    # 启用监控
    metrics_enabled: bool = True
    
    class Config:
        env_file = ".env.production"
        env_file_encoding = 'utf-8'


# 配置工厂
config_map = {
    "development": DevelopmentConfig,
    "testing": TestingConfig,
    "staging": StagingConfig,
    "production": ProductionConfig,
}


@lru_cache()
def get_settings() -> BaseConfig:
    """获取配置实例（单例模式）"""
    # 从环境变量获取环境名称，默认为development
    env = os.getenv("ENVIRONMENT", "development").lower()
    
    # 获取对应的配置类
    config_class = config_map.get(env, DevelopmentConfig)
    
    print(f"🔧 Loading {env} configuration...")
    return config_class()


# 全局配置实例
settings = get_settings()
